import { ref, computed, onMounted, onUnmounted, nextTick, type Ref } from 'vue'

interface VirtualItem {
  id: string
  index: number
  top: number
  height: number
  data: any
}

export function useVirtualScroll(
  containerRef: Ref<HTMLElement | null>,
  items: Ref<any[]>,
  options: {
    itemHeight: number // 预估的单项高度
    overscan?: number  // 额外渲染的项目数量（上下各几项）
  }
) {
  const { itemHeight, overscan = 5 } = options
  
  // 响应式状态
  const scrollTop = ref(0)
  const containerHeight = ref(0)
  const itemHeights = ref<Map<string, number>>(new Map())
  
  // 虚拟项目列表 - 包含每个消息的位置信息
  const virtualItems = computed<VirtualItem[]>(() => {
    let top = 0
    return items.value.map((item, index) => {
      const id = item._id || item.timestamp
      const height = itemHeights.value.get(id) || itemHeight
      const virtualItem = { id, index, top, height, data: item }
      top += height
      return virtualItem
    })
  })
  
  // 总高度 - 用于维持滚动条的正确行为
  const totalHeight = computed(() => {
    const lastItem = virtualItems.value[virtualItems.value.length - 1]
    return lastItem ? lastItem.top + lastItem.height : 0
  })
  
  // 可见范围的起始和结束索引
  const visibleRange = computed(() => {
    if (!containerHeight.value) return { start: 0, end: 0 }
    
    const scrollEnd = scrollTop.value + containerHeight.value
    
    // 二分查找起始索引
    let start = 0
    let end = virtualItems.value.length - 1
    while (start <= end) {
      const mid = Math.floor((start + end) / 2)
      const item = virtualItems.value[mid]
      if (item.top <= scrollTop.value) {
        start = mid + 1
      } else {
        end = mid - 1
      }
    }
    const startIndex = Math.max(0, end - overscan)
    
    // 二分查找结束索引
    start = 0
    end = virtualItems.value.length - 1
    while (start <= end) {
      const mid = Math.floor((start + end) / 2)
      const item = virtualItems.value[mid]
      if (item.top + item.height <= scrollEnd) {
        start = mid + 1
      } else {
        end = mid - 1
      }
    }
    const endIndex = Math.min(virtualItems.value.length - 1, start + overscan)
    
    return { start: startIndex, end: endIndex }
  })
  
  // 可见的虚拟项目
  const visibleItems = computed(() => {
    const { start, end } = visibleRange.value
    return virtualItems.value.slice(start, end + 1)
  })
  
  // 滚动事件处理
  const handleScroll = () => {
    if (containerRef.value) {
      scrollTop.value = containerRef.value.scrollTop
    }
  }
  
  // 更新容器高度
  const updateContainerHeight = () => {
    if (containerRef.value) {
      containerHeight.value = containerRef.value.clientHeight
    }
  }
  
  // 更新单个项目的高度
  const updateItemHeight = (id: string, height: number) => {
    if (itemHeights.value.get(id) !== height) {
      itemHeights.value.set(id, height)
    }
  }
  
  // 滚动到底部
  const scrollToBottom = async () => {
    await nextTick()
    if (containerRef.value) {
      containerRef.value.scrollTop = totalHeight.value
    }
  }
  
  // 滚动到指定消息
  const scrollToMessage = async (messageId: string) => {
    await nextTick()
    const item = virtualItems.value.find(item => item.id === messageId)
    if (item && containerRef.value) {
      containerRef.value.scrollTop = item.top
    }
  }
  
  // 生命周期管理
  onMounted(() => {
    updateContainerHeight()
    window.addEventListener('resize', updateContainerHeight)
  })
  
  onUnmounted(() => {
    window.removeEventListener('resize', updateContainerHeight)
  })
  
  return {
    // 响应式数据
    totalHeight,
    visibleItems,
    
    // 方法
    handleScroll,
    updateItemHeight,
    scrollToBottom,
    scrollToMessage
  }
}